
/* own header files */
#include "XdkAppInfo.h"

#undef BCDS_MODULE_ID  /* Module ID define before including Basics package*/
#define BCDS_MODULE_ID XDK_APP_MODULE_ID_APP_CONTROLLER

/* own header files */
#include "AppController.h"

/* system header files */
#include <stdio.h>

/* additional interface header files */
#include "XDK_WLAN.h"
#include "XDK_ServalPAL.h"
#include "XDK_HTTPRestClient.h"
#include "XDK_SNTP.h"
#include "BCDS_BSP_Board.h"

#include "BCDS_WlanNetworkConfig.h"
#include "BCDS_WlanNetworkConnect.h"
#include "BCDS_CmdProcessor.h"
#include "BCDS_Assert.h"
#include "XDK_Utils.h"
#include "FreeRTOS.h"
#include "task.h"

/* constant definitions ***************************************************** */
Retcode_T SaveCfgAndReset(const char * buf);
extern char bleDeviceName[];

/* local variables ********************************************************** */

#if HTTP_SECURE_ENABLE
static SNTP_Setup_T SNTPSetupInfo =
        {
                .ServerUrl = SNTP_SERVER_URL,
                .ServerPort = SNTP_SERVER_PORT,
        };/**< SNTP setup parameters */
#endif /* HTTP_SECURE_ENABLE */

static HTTPRestClient_Setup_T HTTPRestClientSetupInfo =
        {
                .IsSecure = HTTP_SECURE_ENABLE,
        };/**< HTTP rest client setup parameters */

/*
 * @todo - Use only HTTP_DEST_SERVER_PORT in the header for secure and non-secure.
 * And remove the below 6 lines of the macros
 */
#if HTTP_SECURE_ENABLE
#ifdef HTTP_DEST_SERVER_PORT
#undef HTTP_DEST_SERVER_PORT
#endif /* #ifdef HTTP_DEST_SERVER_PORT */
#define HTTP_DEST_SERVER_PORT        HTTP_DEST_SERVER_PORT_SECURE
#endif /* if HTTP_SECURE_ENABLE */

static HTTPRestClient_Config_T HTTPRestClientConfigInfo =
        {
                .IsSecure = HTTP_SECURE_ENABLE,
                .DestinationServerUrl = HTTP_DEST_SERVER_HOST,
                .DestinationServerPort = HTTP_DEST_SERVER_PORT,
                .RequestMaxDownloadSize = REQUEST_MAX_DOWNLOAD_SIZE,
        }; /**< HTTP rest client configuration parameters */

static HTTPRestClient_Post_T HTTPRestClientPostInfo =
        {
                .Payload = POST_REQUEST_BODY,
                .PayloadLength = (sizeof(POST_REQUEST_BODY) - 1U),
                .Url = HTTP_DEST_POST_PATH,
                .RequestCustomHeader0 = POST_REQUEST_CUSTOM_HEADER_0,
                .RequestCustomHeader1 = POST_REQUEST_CUSTOM_HEADER_1,
        }; /**< HTTP rest client POST parameters */

/**
 * @brief   The HTTP GET request response callback.
 *
 * @param [in] responseContent
 * Pointer to the GET request response
 *
 * @param [in] responseContentLen
 * Length of the GET request response
 *
 * @param [in] isLastMessage
 * Boolean to represent if it is the last part of the ongoing message
 */


static xTaskHandle AppHttpTaskHandle = NULL; /**< OS thread handle for Application controller */

/* global variables ********************************************************* */

/* inline functions ********************************************************* */

/* local functions ********************************************************** */

/** Refer function definition for description */

static void HTTPRestClientGetCB(const char* responseContent, uint32_t responseContentLen, bool isLastMessage)
{
    BCDS_UNUSED(isLastMessage);

    if ((NULL != responseContent) && (0UL != responseContentLen))
    {
        printf("HTTP GET response: %d,[%s]\r\n", (int) responseContentLen, responseContent);
        SaveCfgAndReset(responseContent);

    }
}


/**
 * @brief Responsible for controlling the HTTP Example application control flow.
 *
 * - Synchronize the node with the SNTP server for time-stamp (if HTTPS)
 * - Check whether the WLAN network connection is available
 * - Do a HTTP rest client POST
 * - Wait for INTER_REQUEST_INTERVAL if POST was successful
 * - Do a HTTP rest client GET if POST was successful
 * - Wait for INTER_REQUEST_INTERVAL if GET was successful
 * - Redo the last 5 steps
 *
 * @param[in] pvParameters
 * Unused
 */
static void AppHttpTaskEntry(void* pvParameters)
{
    BCDS_UNUSED(pvParameters);
    printf("AppHttpTaskEntry\r\n");

    Retcode_T retcode = RETCODE_OK;
    while ( (retcode = AppControllerValidateWLANConnectivity()) != RETCODE_OK ){
    	vTaskDelay(pdMS_TO_TICKS(INTER_REQUEST_INTERVAL));
    }

    printf("Connect is ready!\r\n");

#if HTTP_SECURE_ENABLE

    uint64_t sntpTimeStampFromServer = 0UL;

    /* We Synchronize the node with the SNTP server for time-stamp.
     * Since there is no point in doing a HTTPS communication without a valid time */
    do
    {
        retcode = SNTP_GetTimeFromServer(&sntpTimeStampFromServer, APP_RESPONSE_FROM_SNTP_SERVER_TIMEOUT);
        if ((RETCODE_OK != retcode) || (0UL == sntpTimeStampFromServer))
        {
            printf("AppHttpTaskEntry : SNTP server time was not synchronized. Retrying...\r\n");
        }
    } while (0UL == sntpTimeStampFromServer);

    BCDS_UNUSED(sntpTimeStampFromServer); /* Copy of sntpTimeStampFromServer will be used be HTTPS for TLS handshake */
#endif /* HTTP_SECURE_ENABLE */

    while (1)
    {
        /* Resetting / clearing the necessary buffers / variables for re-use */
        retcode = RETCODE_OK;

        /* Check whether the WLAN network connection is available */
        retcode = AppControllerValidateWLANConnectivity();

        /* Do a HTTP rest client POST */
        if (RETCODE_OK == retcode)
        {
            //retcode = HTTPRestClient_Post(&HTTPRestClientConfigInfo, &HTTPRestClientPostInfo, APP_RESPONSE_FROM_HTTP_SERVER_POST_TIMEOUT);
        }
        if (RETCODE_OK == retcode)
        {
        	char edgeInfoUrl[32] = {HTTP_DEST_GET_PATH};
        	strcat(edgeInfoUrl, bleDeviceName);
        	HTTPRestClient_Get_T HTTPRestClientGetInfo =  {
        			.Url = edgeInfoUrl,.GetCB = HTTPRestClientGetCB, .GetOffset = 0UL  	        };
            /* Do a HTTP rest client GET */
            retcode = HTTPRestClient_Get(&HTTPRestClientConfigInfo, &HTTPRestClientGetInfo, APP_RESPONSE_FROM_HTTP_SERVER_GET_TIMEOUT);
        }
        if (RETCODE_OK == retcode)
        {
            /* Wait for INTER_REQUEST_INTERVAL */
            vTaskDelay(pdMS_TO_TICKS(APP_QUERY_UPSTREAM_CONFIG_TIMEOUT));
        }
        if (RETCODE_OK != retcode)
        {
            printf("Error in Post/get request: Will trigger another post/get after INTER_REQUEST_INTERVAL\r\n");
            vTaskDelay(pdMS_TO_TICKS(APP_QUERY_UPSTREAM_CONFIG_TIMEOUT));
        }
    }
}

/**
 * @brief To enable the necessary modules for the application
 * - WLAN
 * - ServalPAL
 * - SNTP (if HTTPS)
 * - HTTP rest client
 *
 * @param[in] param1
 * Unused
 *
 * @param[in] param2
 * Unused
 */
int http_st = 0;
void AppHttpEnable(void * param1, uint32_t param2)
{
    BCDS_UNUSED(param1);
    BCDS_UNUSED(param2);

    Retcode_T retcode;
    retcode = ServalPAL_Enable();
    http_st = 0x10 | retcode;

#if HTTP_SECURE_ENABLE
    if (RETCODE_OK == retcode)
    {
        retcode = SNTP_Enable();
    }
#endif /* HTTP_SECURE_ENABLE */

    if (RETCODE_OK == retcode)
    {
        retcode = HTTPRestClient_Enable();
        http_st |= (0x1000|(retcode<<8));

    }
    if (RETCODE_OK == retcode)
    {
        if (pdPASS != xTaskCreate(AppHttpTaskEntry, (const char * const ) "Http task", TASK_STACK_SIZE_APP_CONTROLLER, NULL, TASK_PRIO_APP_CONTROLLER-1, &AppHttpTaskHandle))
        {
            retcode = RETCODE(RETCODE_SEVERITY_ERROR, RETCODE_OUT_OF_RESOURCES);
            http_st |= (0x100000|(retcode<<16));
        }
    }
}

Retcode_T AppHttpSetup( CmdProcessor_T * appCmdProcessor)
{
    Retcode_T retcode = ServalPAL_Setup(appCmdProcessor);
    if (RETCODE_OK == retcode)
    {
    	retcode = HTTPRestClient_Setup(&HTTPRestClientSetupInfo);
    }
    return retcode;
}


/**@} */
/** ************************************************************************* */
